package top.superflow.version.db

import top.superflow.exception.RequestUnsupportedException
import top.superflow.verify.Ensure
import top.superflow.version.compare.suggestion.Suggestion
import top.superflow.version.db.compare.{CheckChildrenSuggestion, MetadataConsistencySuggestion, MetadataInconsistentHappened}

import scala.collection.mutable.{ListBuffer, Map}

trait EntityAware extends Version with Ensure{
  
  protected val entityVersions : Map[String, EntityVersion] = Map[String, EntityVersion]()
  
  def getEntityVersions : Map[String, EntityVersion] = {
    this.entityVersions
  }
  
  def getEntityVersionSize = {
    this.entityVersions.size
  }
  
  def compare (targetStructure : Any): Option[Suggestion] = {
    targetStructure match {
      case dvp : Option[_] =>{
        if(dvp == None || dvp.isEmpty){
          Some(new MetadataConsistencySuggestion(new MetadataInconsistentHappened(this, null), new CheckChildrenSuggestion()))
        }else{
          this.compare(dvp.get)
        }
      }
      
      case ev: EntityAware => {
        val suggestionsForChildren = getSuggestionsForChildren(ev)
        
        summarizeSuggestion(suggestionsForChildren)
      }
      
      case _ => {
        throw new RequestUnsupportedException(targetStructure)
      }
    }
    
  }
  
  def getSuggestionsForChildren (targetWholeDataVersion : EntityAware): List[Suggestion] = {
    val possibleSuggestionList = ListBuffer[Suggestion]()
    
    for((entityName , childEntity) <- this.entityVersions){
      val childFromTargetEntity = targetWholeDataVersion.getMatchedChild(entityName)
      
      val sgtForTheEntity = childEntity.compare(childFromTargetEntity)
      
      if(!sgtForTheEntity.isEmpty){
         possibleSuggestionList += sgtForTheEntity.get 
      }
    }
    
    possibleSuggestionList.toList
  }
  
    
  def getMatchedChild (childDataVersionKey : Any) : Option[Version] = {
    childDataVersionKey match {
      case entityKey : String => {
        this.entityVersions.get(entityKey)
      }
      
      case entity : EntityVersion => {
        this.entityVersions.get(entity.name.get)
      }
      
      case _ => {
        None
      }
    }
    
  }
}